#!/usr/bin/env python3
# _*_coding:utf-8 _*_
__author__ = "Gao"

import importlib
import jwt
from django.utils.translation import ugettext as _
from rest_framework import exceptions
from rest_framework_jwt.settings import api_settings
from rest_framework.authentication import  get_authorization_header
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from django.conf import settings
from django.utils.encoding import smart_text
from celery.exceptions import TimeoutError
from my_rest.exceptions import ServiceUnavilable,ParmError
import json
from rest_framework import serializers
import traceback

from core.tasks import user_tasks
from django.conf import settings

jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
jwt_get_username_from_payload = api_settings.JWT_PAYLOAD_GET_USERNAME_HANDLER


class MyJSONWebTokenAuthentication(JSONWebTokenAuthentication):
    """重构JWT认证"""

    def get_jwt_value(self, request):

        auth = get_authorization_header(request).split()
        auth_header_prefix = api_settings.JWT_AUTH_HEADER_PREFIX.lower()

        if not auth:
            if api_settings.JWT_AUTH_COOKIE:
                return request.COOKIES.get(api_settings.JWT_AUTH_COOKIE)
            return None

        if smart_text(auth[0].lower()) != auth_header_prefix:
            return None

        if len(auth) == 1:
            msg = _('不合法的请求头.没有提供凭证.')
            raise exceptions.AuthenticationFailed(msg)
        elif len(auth) > 2:
            msg = _('Invalid Authorization header. Credentials string '
                    'should not contain spaces.')
            raise exceptions.AuthenticationFailed(msg)

        return auth[1]

    def authenticate(self, request):
        """
        Returns a two-tuple of `User` and token if a valid signature has been
        supplied using JWT-based authentication.  Otherwise returns `None`.
        """
        if settings.IF_DEV:    # 开发环境不做验证，返回测试用户
            user = {
                'id': 1,
                'is_admin': True,
                'is_authed': True  # 授权
            }
            return (user, '1')

        jwt_value = self.get_jwt_value(request)
        if jwt_value is None:
            return None
        try:
            payload = jwt_decode_handler(jwt_value)
        except jwt.ExpiredSignature:
            msg = _('token 已过期')
            raise exceptions.AuthenticationFailed(msg)
        except jwt.DecodeError:
            msg = _('不合法的token')
            raise exceptions.AuthenticationFailed(msg)
        except jwt.InvalidTokenError:
            raise exceptions.AuthenticationFailed()

        user = self.authenticate_credentials(payload)

        return (user, jwt_value)

    def authenticate_credentials(self, payload):
        """
        根据payload获取user实例
        """

        uid = payload.get('id')
        code = payload.get('code')
        username = payload.get('username')
        is_admin = payload.get('is_admin')

        if not all([uid,code,username]):
            msg = _('不合法的token')
            raise exceptions.AuthenticationFailed(msg)

        conditions = {'id': uid}
        fields = ['id','is_active','is_admin']
        task_res = json.loads(user_tasks.get_users(*fields, **conditions))    # 每次调接口时都会去数据库查询账户状态

        if task_res['status'] ==400:
            msg = _('参数错误')
            raise serializers.ValidationError(msg)
        try:
            user = task_res['data'][0]
        except IndexError:
            msg = _("该帐号不存在")
            raise serializers.ValidationError(msg)
        if not user['is_active']:
            msg = _('该账户已被禁用')
            raise exceptions.AuthenticationFailed(msg)

        user = {
            'id': user['id'],
            'is_admin': user['is_admin'],
            'is_authed': True    # 授权
        }

        return user    # 返回的对象会放到request中
